package org.wendu.wdoa.common.security;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Field;
import java.util.Map;

@Slf4j
public class LoginFilter extends UsernamePasswordAuthenticationFilter {

    @SneakyThrows //转换异常为非受查形式
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
            throws AuthenticationException {

        Field postOnlyField  = UsernamePasswordAuthenticationFilter.class.getDeclaredField("postOnly");
        postOnlyField.setAccessible(true);
        boolean postOnly = (Boolean) postOnlyField.get(this);

        if ( postOnly && !request.getMethod().equals("POST")) {
            throw new AuthenticationServiceException("Authentication method not supported: " +
                    request.getMethod());
        }
        if(!request.getContentType().contains(MediaType.APPLICATION_JSON_VALUE)){
            return super.attemptAuthentication(request,response);
        }
        ObjectMapper objectMapper = new ObjectMapper();
        Map<String,String> map = objectMapper.readValue(request.getInputStream(), Map.class);

        String username = map.get(this.getUsernameParameter());
        username = (username != null) ? username : "";
        username = username.trim();

        String password = map.get(this.getPasswordParameter());
        password = (password != null) ? password : "";

        UsernamePasswordAuthenticationToken authRequest =
                new UsernamePasswordAuthenticationToken(username, password);
        // Allow subclasses to set the "details" property
        setDetails(request, authRequest);
        return this.getAuthenticationManager().authenticate(authRequest);
    }
}